/*
 * TokenCompartido.cpp
 *
 *  Created on: 03/08/2014
 *      Author: migue
 */

#include "TokenCompartido.h"
#include <iostream>
#include <iomanip>
#include <string.h>
#include <stdio.h>

using namespace std;

TokenCompartido::TokenCompartido() :
_mutex(RUTA,1,ID_MTX_TOKEN_COMP), _shm(RUTA, ID_SHM_TOKEN_COMP, sizeof(TOKEN))
{
	_token = NULL;
}

TokenCompartido::~TokenCompartido() {
	if (_token != NULL)
		delete _token;
}

void TokenCompartido::actualizar(const TOKEN& token) {
	_mutex.wait();
	_shm.escribir(0, &token, sizeof(TOKEN));
	_mutex.signal();
}

void TokenCompartido::recuperar(TOKEN& token) {
	_mutex.wait();
	_shm.leer(0, &token, sizeof(TOKEN));
	_mutex.signal();
}


void TokenCompartido::inicializar() {
	Semaforo s(RUTA,1,ID_MTX_TOKEN_COMP,true);
	MemoriaCompartida m(RUTA, ID_SHM_TOKEN_COMP, sizeof(TOKEN));

	s.inicializar(1);

	TOKEN token;
	memset(&token, 0, sizeof(TOKEN));

	cout << "token comp inicializado" << endl;
}

void TokenCompartido::destruir() {
	Semaforo::destruirSemaforo(RUTA,1,ID_MTX_TOKEN_COMP);
	MemoriaCompartida m(RUTA, ID_SHM_TOKEN_COMP, sizeof(TOKEN));
	m.destruir();

	cout << "token comp destruido" << endl;
}

void TokenCompartido::mostrarEstado() {
	if (_token == NULL)
		_token = new TOKEN();

	_mutex.wait();
	_shm.leer(0, _token, sizeof(TOKEN));
	_mutex.signal();

//	SemaforoRemoto sem(ID_MUTEX_PARQUE, id_admin, id_broker_conectado);
//	ParqueRemoto parque(id_admin, id_broker_conectado);
//
//	sem.wait();
//	int cantActual = parque.personasDentro();
//	bool abierto = parque.parqueAbierto();
//	int cantRepuestos = parque.busesDeRepuesto();
//	sem.signal();

	int cantActual = _token->parque.cantPersonas;
	bool abierto = _token->parque.parqueAbierto;
	int cantRepuestos = _token->parque.busesDeRepuestos;

	printf("%c[1;31;40m",27);
	cout << "Capacidad :" << CANT_MAX_PARQUE;
	cout << " |  Estado: ";
	if (abierto) {
		cout << "Abierto.";
	}
	else {
		cout << "Cerrado.";
	}

	cout << " | Personas Dentro: " << setfill(' ') << std::setw(5) << cantActual;

	cout << " | Buses Rep. Disp.: " << cantRepuestos << endl;

	cout << "Mutex Parque: "<< _token->semParque << endl;


	// mostrando las salas

	int cantPers;
	Tipos::EstadoBUS estBus;

	for (int i = 0; i < CANT_ENTRADAS ; ++i) {
		int numSala = i+1;

		printf("%c[1;32;40m",27);

		cout << "Mutex Ent: " << _token->semSalasEntrada[i];
		cout << " | Ent LLena: " << _token->semSalasLlenoEntrada[i];
		cout <<"    |   ";
		cout <<"Sem BUS: " << _token->semBus[i];
		cout <<"     |  ";
		cout <<"Mutex Zoo: " << _token->semSalasZoo[i];
		cout <<"| Zoo Lleno: " << _token->semSalasLlenoZoo[i] << endl;




		printf("%c[1;33;40m",27);
		cout << "SalaEnt " << numSala <<": ";

		cantPers = _token->salasEntrada[i].cantPersonas;
		estBus = _token->salasEntrada[i].estadoBUS;


		cout << cantPers << " pers. " ;

		if (estBus == Tipos::BUS_PARADO) {
			cout << " - BUS PARADO - ";
		}
		else if (estBus == Tipos::BUS_ACTIVO ){
			cout << " -            - ";
		}
		else if (estBus == Tipos::BUS_SUBIENDO_PERS ){
			cout << " -  SUBIENDO  - ";
		}
		else if (estBus == Tipos::BUS_BAJANDO_PERS ){
			cout << " -  BAJANDO   - ";
		}
		else {
			cout << " - BUS_ERROR  - ";
		}


		cout << "    |X|     SalaZoo " << numSala <<": ";

		cantPers = _token->salasZoo[i].cantPersonas;
		estBus = _token->salasZoo[i].estadoBUS;

		cout << cantPers << " pers. " ;

		if (estBus == Tipos::BUS_PARADO) {
			cout << " - BUS PARADO - ";
		}
		else if (estBus == Tipos::BUS_ACTIVO ){
			cout << " -            - ";
		}
		else if (estBus == Tipos::BUS_SUBIENDO_PERS ){
			cout << " -  SUBIENDO  - ";
		}
		else if (estBus == Tipos::BUS_BAJANDO_PERS ){
			cout << " -  BAJANDO   - ";
		}
		else {
			cout << " - BUS_ERROR  - ";
		}

		printf("%c[1;34;40m",27);
		cout << endl;
		mostrarSala(&_token->salasEntrada[i], &_token->salasZoo[i]);

		cout << "----------------------------------------------------------------------------------";

		cout << endl;
	}

	printf("%c[0m",27);
}


void TokenCompartido::mostrarSala(SALA *salaEnt, SALA *salaZoo) {

	int pasadas = CANTMAX / 5;

	for (int j = 0, k = 0 ; k < pasadas ; j += 5, ++k ) {

		for (int i = 0; (j + i) < CANTMAX && i < 5 ; ++i) {
			imprimirLugar(salaEnt->personas[i + j]);
		}

		cout << "    |X|    ";

		for (int i = 0; i < CANTMAX && i < 5 ; ++i) {
			imprimirLugar(salaZoo->personas[i + j]);
		}

		cout << endl;

	}

}


void TokenCompartido::imprimirLugar(int id) {



	if (id > 0) {
		cout << "[" << setfill(' ') << std::setw(4);
		cout << id << "] ";
	}
	else if (id < 0) {
		cout <<"#";
		cout << setfill(' ') << std::setw(3) << -id;
		cout << "# ";
	}
	else {
		cout << "[";
		// esta linea es solo para debug
		cout << setfill(' ') << std::setw(4);
		cout << " ";
		cout << "] ";
	}

}

void TokenCompartido::pausarBroker() {
	_mutex.wait();
	cout << "Broker pausado." << endl;
}

void TokenCompartido::retomarBroker() {
	_mutex.signal();
	cout << "Broker retomado." << endl;
}
